#include "rgbcapture.h"
#include <QImage>
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>
RgbCapture::RgbCapture(QObject *parent) : QObject(parent)
{
    // 初始化FFmpeg库
    avdevice_register_all();
    avformat_network_init();
}

RgbCapture::~RgbCapture()
{
     stop();
}
void RgbCapture::setConnectTimeout(int ms)
{
    m_connectTimeout = ms;
}

void RgbCapture::setReadTimeout(int ms)
{
    m_readTimeout = ms;
}

void RgbCapture::setOverallTimeout(int ms)
{
    m_overallTimeout = ms;
}
void RgbCapture::start(const QString &url)
{
    if (m_running)
        return;

    m_running = true;
    emit started();

    QFuture<void> future = QtConcurrent::run([this, url]() {
        // 打开输入流(带连接超时)
        AVDictionary* options = nullptr;
        av_dict_set(&options, "timeout", QString::number(m_connectTimeout).toUtf8().constData(), 0);
        // 打开输入流
        m_formatContext = nullptr;
        if (avformat_open_input(&m_formatContext, url.toUtf8().constData(), nullptr, &options) != 0) {
            av_dict_free(&options);
            emit error("无法打开输入流");
            m_running = false;
            emit stopped();
            return;
        }
        av_dict_free(&options);
        // 查找流信息
        if (avformat_find_stream_info(m_formatContext, nullptr) < 0) {
            emit error("无法获取流信息");
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 查找视频流
        m_videoStreamIndex = -1;
        for (unsigned int i = 0; i < m_formatContext->nb_streams; i++) {
            if (m_formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                m_videoStreamIndex = i;
                break;
            }
        }

        if (m_videoStreamIndex == -1) {
            emit error("未找到视频流");
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 获取解码器
        AVCodecParameters *codecParameters = m_formatContext->streams[m_videoStreamIndex]->codecpar;
        const AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id);
        if (!codec) {
            emit error("未找到合适的解码器");
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 分配解码器上下文
        m_codecContext = avcodec_alloc_context3(codec);
        if (!m_codecContext) {
            emit error("无法分配解码器上下文");
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 填充解码器上下文
        if (avcodec_parameters_to_context(m_codecContext, codecParameters) < 0) {
            emit error("无法填充解码器上下文");
            avcodec_free_context(&m_codecContext);
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 打开解码器
        if (avcodec_open2(m_codecContext, codec, nullptr) < 0) {
            emit error("无法打开解码器");
            avcodec_free_context(&m_codecContext);
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 设置图像转换上下文
        m_swsContext = sws_getContext(m_codecContext->width, m_codecContext->height,
                                      m_codecContext->pix_fmt, m_codecContext->width, m_codecContext->height,
                                      AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
        if (!m_swsContext) {
            emit error("无法初始化图像转换上下文");
            avcodec_free_context(&m_codecContext);
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 分配帧缓冲区
        AVFrame *frame = av_frame_alloc();
        AVFrame *frameRGB = av_frame_alloc();
        if (!frame || !frameRGB) {
            emit error("无法分配帧缓冲区");
            sws_freeContext(m_swsContext);
            avcodec_free_context(&m_codecContext);
            avformat_close_input(&m_formatContext);
            m_running = false;
            emit stopped();
            return;
        }

        // 分配RGB缓冲区
        int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_codecContext->width,
                                                m_codecContext->height, 1);
        uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
        av_image_fill_arrays(frameRGB->data, frameRGB->linesize, buffer, AV_PIX_FMT_RGB24,
                             m_codecContext->width, m_codecContext->height, 1);

        // 读取和处理帧
        AVPacket packet;
        while (m_running && av_read_frame(m_formatContext, &packet) >= 0) {
            if (packet.stream_index == m_videoStreamIndex) {
                // 发送数据包到解码器
                if (avcodec_send_packet(m_codecContext, &packet) < 0) {
                    emit error("发送数据包到解码器失败");
                    continue;
                }

                // 从解码器接收帧
                while (avcodec_receive_frame(m_codecContext, frame) == 0) {
                    // 转换为RGB格式
                    sws_scale(m_swsContext, (const uint8_t *const *)frame->data, frame->linesize,
                              0, m_codecContext->height, frameRGB->data, frameRGB->linesize);

                    // 创建QImage并发送
                    QImage image(frameRGB->data[0], m_codecContext->width, m_codecContext->height,
                                 frameRGB->linesize[0], QImage::Format_RGB888);
                    emit frameReady(image.copy());
                }
            }
            av_packet_unref(&packet);
        }

        // 清理资源
        av_free(buffer);
        av_frame_free(&frameRGB);
        av_frame_free(&frame);
        sws_freeContext(m_swsContext);
        avcodec_free_context(&m_codecContext);
        avformat_close_input(&m_formatContext);

        m_running = false;
        emit stopped();
        emit clearFrame(); // 新增
    });
}

void RgbCapture::stop()
{
    m_running = false;
}
